package com.coderg.gmall.oauth2.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.coderg.gmall.common.util.IpUtil;
import com.coderg.gmall.model.cart.CartInfo;
import com.coderg.gmall.oauth2.service.LoginService;
import com.coderg.gmall.oauth2.util.AuthToken;
import com.coderg.gmall.rabbitMq.constant.RabbitConst;
import com.coderg.gmall.rabbitMq.service.RabbitService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @Description
 * @Author CoderG
 * @Date 2025/5/31 20:41
 **/
@Service
@RequiredArgsConstructor
public class LoginServiceImpl implements LoginService {

    private final RestTemplate restTemplate;

    private final LoadBalancerClient loadBalancerClient;

    private final HttpServletRequest httpServletRequest;

    private final StringRedisTemplate stringRedisTemplate;

    private final RabbitService rabbitService;

    private final RedisTemplate redisTemplate;


    /**
     * 用户登录
     *
     * @param username
     * @param password
     * @return
     */
    @Override
    public AuthToken login(String username, String password, List<CartInfo> cartInfos) {
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
            return null;
        }
        // 创建 HttpHeaders 对象并设置请求头
        MultiValueMap<String, String> headers = new HttpHeaders();
        // 设置 Authorization
        headers.set("Authorization", getClientId());
        // 构建请求body参数，即请求体的JSON实体类，这里简单模拟
        MultiValueMap<String, String> body = new HttpHeaders();
        body.set("username", username);
        body.set("password", password);
        body.set("grant_type", "password");
        // 创建 HttpEntity 对象，将请求头和请求体（如果有）封装在一起
        HttpEntity requestEntity = new HttpEntity(body, headers);
        // 发送 post 请求
        ServiceInstance serviceInstance = loadBalancerClient.choose("service-oauth");
        URI uri = serviceInstance.getUri();
        String url = uri + "/oauth/token";
        ResponseEntity<LinkedHashMap> response = restTemplate.exchange(
                url,
                HttpMethod.POST,
                requestEntity,
                LinkedHashMap.class
        );
        // 获取响应结果
        LinkedHashMap responseBody = response.getBody();
        AuthToken authToken = new AuthToken();
        authToken.setAccessToken((String) responseBody.get("access_token"));
        authToken.setRefreshToken((String) responseBody.get("refresh_token"));
        authToken.setJti((String) responseBody.get("jti"));
        //绑定用户ip防止token被盗取
        String ipAddress = IpUtil.getIpAddress(httpServletRequest);
        stringRedisTemplate.opsForValue().set(ipAddress, authToken.getAccessToken(), 7, TimeUnit.DAYS);
        // : 2025/6/5  触发购物车合并 然后将购物车数据写入redis  缓存不一致问题
        if (cartInfos == null || cartInfos.isEmpty()) {
            cartInfos = Collections.emptyList();
        }
        String jsonCarts = JSONObject.toJSONString(cartInfos);
        String jsonStr = username + "--" + jsonCarts;
        rabbitService.sendMessage(RabbitConst.CART_EXCHANGE,
                RabbitConst.CART_ROUTING_KEY,
                jsonStr);

        return authToken;
    }

    @Value("${clientId}")
    String clientId;
    @Value("${client_secret}")
    String clientSecret;

    private String getClientId() {
        byte[] encode = Base64.getEncoder().encode((clientId + ":" + clientSecret).getBytes(StandardCharsets.UTF_8));
        return "Basic " + new String(encode);
    }

    @Override
    public AuthToken logout(String username, String password) {

        return null;
    }
}
